﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using SageKing.Database.EF.Contracts;
using SageKing.Database.Service;

namespace SageKing.Database.EF.Services;

public class TemplateBaseService<TEntity, Tk> : BaseService<TEntity, Tk>
    where TEntity : EntityBase<Tk>, new()
{
    private readonly TemplateContext _context;

    public TemplateBaseService(TemplateContext context)
    {
        _context = context;
    }

    public override async Task<bool> Add(TEntity entity)
    {
        await _context.Set<TEntity>().AddAsync(entity);

        await _context.SaveChangesAsync();

        return true;
    }

    public override async Task<bool> Add(IEnumerable<TEntity> entity)
    {
        await _context.Set<TEntity>().AddRangeAsync(entity);

        await _context.SaveChangesAsync();

        return true;
    }

    public override async Task<bool> Add(IList<TEntity> entitys)
    {
        await _context.Set<TEntity>().AddRangeAsync(entitys);

        await _context.SaveChangesAsync();

        return true;
    }

    public override async Task<TEntity> AddReturnEntityAsync(TEntity entity)
    {
        await _context.Set<TEntity>().AddAsync(entity);

        await _context.SaveChangesAsync();

        return entity;
    }

    public override async Task<Tk> AddReturnId(TEntity entity, int type = 0)
    {
        await _context.Set<TEntity>().AddAsync(entity);

        await _context.SaveChangesAsync();

        return entity.Id;
    }

    public override async Task<int> CountAsync(Expression<Func<TEntity, bool>> whereFunc)
    {
        return await _context.Set<TEntity>().Where(whereFunc).CountAsync();
    }

    public override async Task<bool> Delete(Tk id)
    {
        await _context.Set<TEntity>().Where(a => a.Id.Equals(id)).ExecuteDeleteAsync();
        await _context.SaveChangesAsync();
        return true;
    }

    public override async Task<TEntity> GetDetail(Tk id)
    {
        return await _context.Set<TEntity>()
         .FindAsync(id);
    }

    public override async Task<List<TEntity>> GetList()
    {
        return await _context.Set<TEntity>().ToListAsync();
    }

    public override async Task<List<TEntity>> GetList(Expression<Func<TEntity, bool>> whereFunc)
    {
        return await _context.Set<TEntity>().Where(whereFunc).ToListAsync();
    }

    public override async Task<List<TEntity>> GetList(Expression<Func<TEntity, bool>> whereFunc, Expression<Func<TEntity, object>> orderby, bool orderByType = true)
    {
        return await _context.Set<TEntity>().Where(whereFunc).OrderBy(orderby).ToListAsync();
    }

    public override async Task<PageBase<TEntity>> GetPageAsync(PageBaseInput page)
    {
        var items = await _context.Set<TEntity>().Take(page.PageSize).Skip(page.GetSkipCount()).ToListAsync();
        var allcount = await _context.Set<TEntity>().CountAsync();
        var result = new PageBase<TEntity>()
        {
            Total = allcount,
            Page = page.Page,
            PageSize = page.PageSize,
            Items = items
        };
        return result;
    }

    public override async Task<PageBase<TEntity>> GetPage(PageBaseInput page, Expression<Func<TEntity, object>> orderby, bool orderByAsc = true)
    {
        var items = await _context.Set<TEntity>().OrderBy(orderby).Take(page.PageSize).Skip(page.GetSkipCount()).ToListAsync();
        var allcount = await _context.Set<TEntity>().CountAsync();
        var result = new PageBase<TEntity>()
        {
            Total = allcount,
            Page = page.Page,
            PageSize = page.PageSize,
            Items = items
        };
        return result;
    }

    public override async Task<PageBase<TEntity>> GetPage(PageBaseInput page, List<(bool, Expression<Func<TEntity, bool>>)> whereIf, Expression<Func<TEntity, object>> orderby, bool orderByAsc = true)
    {
        var tmpdata = _context.Set<TEntity>();
        IQueryable<TEntity> tmpQuery = null;

        IEnumerable<TEntity> items = null;
        int allcount = 0;

        bool isFirst = true;
        foreach (var item in whereIf)
        {
            if (item.Item1)
            {
                tmpQuery = isFirst ? tmpdata.Where(item.Item2) : tmpQuery.Where(item.Item2);
                isFirst = false;
            }
        }

        if (tmpQuery != null)
        {
            items = await tmpQuery.OrderBy(orderby).Take(page.PageSize).Skip(page.GetSkipCount()).ToListAsync();
            allcount = await tmpQuery.CountAsync();
        }
        else
        {
            items = await tmpdata.OrderBy(orderby).Take(page.PageSize).Skip(page.GetSkipCount()).ToListAsync();
            allcount = await tmpdata.CountAsync();

        }
        var result = new PageBase<TEntity>()
        {
            Total = allcount,
            Page = page.Page,
            PageSize = page.PageSize,
            Items = items
        };

        return result;
    }

    public override async Task<int> Update(TEntity entity)
    {
        _context.Entry(entity).State = EntityState.Modified;

        return await _context.SaveChangesAsync();
    }

    public override async Task<int> Update(TEntity entity, Expression<Func<TEntity, object>> updateColumns)
    {
        _context.Entry(entity).State = EntityState.Unchanged;

        _context.Entry(entity).Property(updateColumns).IsModified = true; // 只更新对应字段

        return await _context.SaveChangesAsync();
    }

    public override Task<int> Update(Expression<Func<TEntity, bool>> wherefunc, Expression<Func<TEntity, TEntity>> updateColumns)
    {
        throw new NotImplementedException();
    }

    public override async Task<int> UpdateWithOptLock(TEntity entity)
    {
        _context.Entry(entity).State = EntityState.Modified;

        return await _context.SaveChangesAsync();
    }

    public override async Task<int> UpdateWithOptLock(TEntity entity, Expression<Func<TEntity, object>> updateColumns)
    {
        _context.Entry(entity).State = EntityState.Unchanged;

        _context.Entry(entity).Property(updateColumns).IsModified = true; // 只更新对应字段

        return await _context.SaveChangesAsync();
    }
}
